﻿using Engine;
using Game;
using GameEntitySystem;
using SAGhoul.Blocks;
using SAGhoul.Tartareosity;
using System.Collections.Generic;
using TemplatesDatabase;

namespace SAGhoul
{
    public class SubsystemSAG : SubsystemBlockBehavior, IUpdateable
    {
        public SubsystemBlockEntities m_subsystemBlockEntities;
        public SubsystemBodies m_subsystemBodies;
        public SubsystemSky m_subsystemSky;
        public SubsystemTimeOfDay m_subsystemTimeOfDay;
        public SubsystemSAGArtifactBlockBehavior m_subsystemSAGArtifactBlockBehavior;
        public SubsystemTartareosity m_subsystemTartareosity;
        public SubsystemParticles m_subsystemParticles;
        public SubsystemAudio m_subsystemAudio;
        public SubsystemExplosions m_subsystemExplosions;
        public SubsystemPlayers m_subsystemPlayers;
        public override int[] HandledBlocks => [BlocksManager.GetBlockIndex<SnowballBlock>()];
        public UpdateOrder UpdateOrder => UpdateOrder.Default;
        public Game.Random m_random = new();
        public bool SAGEnable;
        public Dictionary<int, string> BossData = [];
        public float SkyColorFactor;
        public float SkyBrightness;
        public int NourishmentAcquiredCount;
        public bool IsOptionDecided;
        /// <summary>
        /// 本存档游戏难度
        /// </summary>
        public Difficulty Difficulty
        {
            get; set;
        }

        /// <summary>
        /// 本存档血月周期长度乘数（1，2，3，4；x4天）
        /// </summary>
        public int PeriodLengthMultiplier
        {
            get; set;
        }
        bool m_optionDialogShown;
		public override void Load(ValuesDictionary valuesDictionary)
        {
            base.Load(valuesDictionary);
            m_subsystemBlockEntities = Project.FindSubsystem<SubsystemBlockEntities>(throwOnError: true);
            m_subsystemBodies = Project.FindSubsystem<SubsystemBodies>();
            m_subsystemSky = Project.FindSubsystem<SubsystemSky>();
            m_subsystemTimeOfDay = Project.FindSubsystem<SubsystemTimeOfDay>();
            m_subsystemSAGArtifactBlockBehavior = Project.FindSubsystem<SubsystemSAGArtifactBlockBehavior>(true);
            m_subsystemTartareosity = Project.FindSubsystem<SubsystemTartareosity>(true);
			m_subsystemParticles = Project.FindSubsystem<SubsystemParticles>(true);
            m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(true);
            m_subsystemExplosions = Project.FindSubsystem<SubsystemExplosions>(true);
            m_subsystemPlayers = Project.FindSubsystem<SubsystemPlayers>(true);
            SAGEnable = valuesDictionary.GetValue<bool>("SAGEnable");
			NourishmentAcquiredCount = valuesDictionary.GetValue<int>("NourishmentAcquiredCount", 0);
			IsOptionDecided = valuesDictionary.GetValue<bool>("IsOptionDecided", false);
			Difficulty = (Difficulty)valuesDictionary.GetValue<int>("Difficulty", 2);
			PeriodLengthMultiplier = valuesDictionary.GetValue<int>("PeriodLengthMultiplier",3);
            ValuesDictionary bossData = valuesDictionary.GetValue<ValuesDictionary>("BossData");
            if (bossData != null)
            {
                for (int i = 1; i <= SAGhoulsManager.MaxPeriodCount; i++)
                {
                    string bossName = bossData.GetValue(i.ToString(), string.Empty);
                    if (!string.IsNullOrEmpty(bossName))
                    {
                        BossData.Add(i, bossName);
                    }
                }
            }
        }

        public override void Save(ValuesDictionary valuesDictionary)
        {
            base.Save(valuesDictionary);
            valuesDictionary.SetValue("SAGEnable", SAGEnable);
            valuesDictionary.SetValue("NourishmentAcquiredCount", NourishmentAcquiredCount);
            valuesDictionary.SetValue("IsOptionDecided", IsOptionDecided);
            valuesDictionary.SetValue("Difficulty", (int)Difficulty);
            valuesDictionary.SetValue("PeriodLengthMultiplier", PeriodLengthMultiplier);
        }

        public void Update(float dt)
        {
            if (!m_optionDialogShown && m_subsystemPlayers.ComponentPlayers.Count > 0)
            {
                if (!IsOptionDecided)
                {
                    var dialog = new OptionDialog(this);
                    DialogsManager.ShowDialog(null, dialog);
                }
                else
                {
                    DisplaySetMessage();
                }
                m_optionDialogShown = true;
            }
			SkyBrightness = MathUtils.Max(0, SkyBrightness - 5f * dt);
        }
		public void DisplaySetMessage()
		{
			string text = string.Format(LanguageControl.GetContentWidgets(typeof(OptionDialog).Name, "SetMessage"),
				LanguageControl.Get(typeof(SubsystemSAG).Name, "Difficulties", ((int)Difficulty).ToString()),
				(PeriodLengthMultiplier * 4).ToString());
			foreach (var player in m_subsystemPlayers.ComponentPlayers)
				player?.ComponentGui.DisplaySmallMessage(text, Color.White, true, true);
		}

		public override bool OnHitAsProjectile(CellFace? cellFace, ComponentBody componentBody, WorldItem worldItem)
        {
            if (Terrain.ExtractContents(worldItem.Value) == typeof(SnowballBlock).BlockIndex() && worldItem is Projectile projectile)
            {
                if (projectile.Owner != null)
                {
                    ComponentSAGhouls componentSAGhouls = projectile.Owner.Entity.FindComponent<ComponentSAGhouls>();
                    if (componentSAGhouls != null)
                    {
                        //尸鬼吐雪球产生奇异爆炸
                        m_subsystemSAGArtifactBlockBehavior.AddBizarreExplosion(projectile.Position, 3f, 4f, projectile.Owner);
						//  }
						// if (componentSAGhouls != null && m_random.Bool(0.05f))
						// {//旧版尸鬼吐雪球概率生成鸟
						//     var array = new DynamicArray<ComponentBody>();
						//    m_subsystemBodies.FindBodiesAroundPoint(worldItem.Position.XZ, ComponentSAGPlayer.MaxSpawnRange, array);
						//     if (array.Count(item => item.Entity.FindComponent<ComponentSAGhouls>() != null) < 100)
						//     {
						//        ComponentCreature target = null;
						//        if (componentSAGhouls.m_componentChaseBehavior != null)
						//            target = componentSAGhouls.m_componentChaseBehavior.Target;
						//        Entity entity = DatabaseManager.CreateEntity(Project, "SAGhoul_Bird", throwIfNotFound: true);
						//         ComponentBody body = entity.FindComponent<ComponentBody>(throwOnError: true);
						//         body.Position = worldItem.Position;
						//        body.Rotation = Quaternion.CreateFromAxisAngle(Vector3.UnitY, m_random.Float(0f, (float)Math.PI * 2f));
						//         entity.FindComponent<ComponentSpawn>(throwOnError: true).SpawnDuration = 0.25f;
						//         ComponentChaseBehavior componentChaseBehavior = entity.FindComponent<ComponentChaseBehavior>();
						//         componentChaseBehavior?.Attack(target, 50f, 60f, true);
						//          Project.AddEntity(entity);
						//      }

					}
				}
            }
            return base.OnHitAsProjectile(cellFace, componentBody, worldItem);
        }

        public override void OnBlockAdded(int value, int oldValue, int x, int y, int z)
        {
            int id = Terrain.ExtractContents(value);
            if (id == typeof(Trophy64Block).BlockIndex())
            {
                DatabaseObject databaseObject = Project.GameDatabase.Database.FindDatabaseObject("Trophy64Entity", Project.GameDatabase.EntityTemplateType, throwIfNotFound: true);
                var valuesDictionary = new ValuesDictionary();
                valuesDictionary.PopulateFromDatabaseObject(databaseObject);
                valuesDictionary.GetValue<ValuesDictionary>("BlockEntity").SetValue("Coordinates", new Point3(x, y, z));
                Entity entity = Project.CreateEntity(valuesDictionary);

                entity.FindComponent<ComponentFrame>(throwOnError: true).Position = new Vector3(x + 0.5f, y, z + 0.5f);
                Project.AddEntity(entity);
            }
        }

        public override void OnBlockRemoved(int value, int newValue, int x, int y, int z)
        {
            int id = Terrain.ExtractContents(value);
            if (id == typeof(Trophy64Block).BlockIndex())
            {
                ComponentBlockEntity blockEntity = m_subsystemBlockEntities.GetBlockEntity(x, y, z);
                if (blockEntity != null)
                {
                    Project.RemoveEntity(blockEntity.Entity, disposeEntity: true);
                }
            }
        }

        public override bool OnInteract(TerrainRaycastResult raycastResult, ComponentMiner componentMiner)
        {
            int id = Terrain.ExtractContents(raycastResult.Value);
            if (id == typeof(Trophy64Block).BlockIndex())
            {
                var dialog = new TrophyDialog(this);
                DialogsManager.ShowDialog(componentMiner.ComponentPlayer?.GuiWidget, dialog);
                AudioManager.PlaySound("Audio/UI/ButtonClick", 1f, 0f, 0f);
                return true;
            }
            return base.OnInteract(raycastResult, componentMiner);
        }
    }

    public enum Difficulty
    {
        VeryEasy = 0,
        Easy = 1,
        Normal = 2,
        Hard = 3,
        VeryHard = 4
    }
}